1 : <?php
2 :
3 : /**
4 : * Project: Smarty: the PHP compiling template engine
5 : * File: Smarty.class.php
6 : * SVN: $Id: Smarty.class.php 4745 2013-06-17 18:27:16Z Uwe.Tews@googlemail.com $
7 : *
8 : * This library is free software; you can redistribute it and/or
9 : * modify it under the terms of the GNU Lesser General Public
10 : * License as published by the Free Software Foundation; either
11 : * version 2.1 of the License, or (at your option) any later version.
12 : *
13 : * This library is distributed in the hope that it will be useful,
14 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 : * Lesser General Public License for more details.
17 1 : *
18 1 : * You should have received a copy of the GNU Lesser General Public
19 : * License along with this library; if not, write to the Free Software
20 : * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
21 : *
22 : * For questions, help, comments, discussion, etc., please join the
23 : * Smarty mailing list. Send a blank e-mail to
24 : * smarty-discussion-subscribe@googlegroups.com
25 : *
26 : * @link http://www.smarty.net/
27 : * @copyright 2008 New Digital Group, Inc.
28 : * @author Monte Ohrt <monte at ohrt dot com>
29 : * @author Uwe Tews
30 : * @author Rodney Rehm
31 : * @subpackage Smarty
32 : * @version 3.2-DEV
33 : */
34 : /**
35 : * define shorthand directory separator constant
36 : */
37 : if (!defined('DS')) {
38 : define('DS', DIRECTORY_SEPARATOR);
39 : }
40 :
41 : if (!defined('SMARTY_PLUGINS_DIR')) {
42 : define('SMARTY_PLUGINS_DIR', dirname(__FILE__). DS. 'Plugins' . DS);
43 : }
44 : if (!defined('SMARTY_MBSTRING')) {
45 788 : define('SMARTY_MBSTRING', function_exists('mb_split'));
46 788 : }
47 1 : if (!defined('SMARTY_RESOURCE_CHAR_SET')) {
48 : // UTF-8 can only be done properly when mbstring is available!
49 : /**
50 : * @deprecated in favor of Smarty::$_CHARSET
51 : */
52 : define('SMARTY_RESOURCE_CHAR_SET', SMARTY_MBSTRING ? 'UTF-8' : 'ISO-8859-1');
53 : }
54 : if (!defined('SMARTY_RESOURCE_DATE_FORMAT')) {
55 : /**
56 : * @deprecated in favor of Smarty::$_DATE_FORMAT
57 : */
58 12 : define('SMARTY_RESOURCE_DATE_FORMAT', '%b %e, %Y');
59 12 : }
60 :
61 : /**
62 12 : * This is the main Smarty class
63 : * @package Smarty
64 : * @subpackage Smarty
65 : */
66 : class Smarty extends Smarty_Variable_Methods
67 : {
68 : /* * #@+
69 : * constant definitions
70 : */
71 :
72 : /**
73 : * smarty version
74 : */
75 : const SMARTY_VERSION = 'Smarty 3.2-DEV';
76 :
77 1 : /**
78 : * define variable scopes
79 : */
80 : const SCOPE_LOCAL = 0;
81 : const SCOPE_PARENT = 1;
82 : const SCOPE_ROOT = 2;
83 : const SCOPE_GLOBAL = 3;
84 :
85 : /**
86 : * define object and variable scope type
87 : */
88 : const IS_SMARTY = 0;
89 : const IS_TEMPLATE = 1;
90 : const IS_SUBTPL = 2;
91 : const IS_DATA = 3;
92 : const IS_CONFIG = 4;
93 :
94 : /**
95 : * define resource types
96 : */
97 : const SOURCE = 0;
98 : const COMPILED = 1;
99 : const CACHE = 2;
100 :
101 : /**
102 : * define caching modes
103 : */
104 : const CACHING_OFF = 0;
105 : const CACHING_LIFETIME_CURRENT = 1;
106 : const CACHING_LIFETIME_SAVED = 2;
107 : const CACHING_NOCACHE_CODE = 3; // create nocache code but no cache file
108 : /**
109 : * define constant for clearing cache files be saved expiration datees
110 : */
111 : const CLEAR_EXPIRED = -1;
112 : /**
113 : * define compile check modes
114 : */
115 : const COMPILECHECK_OFF = 0;
116 : const COMPILECHECK_ON = 1;
117 : const COMPILECHECK_CACHEMISS = 2;
118 : /**
119 : * modes for handling of "<?php ... ?>" tags in templates.
120 : */
121 : const PHP_PASSTHRU = 0; //-> print tags as plain text
122 : const PHP_QUOTE = 1; //-> escape tags as entities
123 : const PHP_REMOVE = 2; //-> escape tags as entities
124 : const PHP_ALLOW = 3; //-> escape tags as entities
125 : /**
126 : * filter types
127 : */
128 : const FILTER_POST = 'post';
129 : const FILTER_PRE = 'pre';
130 : const FILTER_OUTPUT = 'output';
131 : const FILTER_VARIABLE = 'variable';
132 : /**
133 : * plugin types
134 : */
135 : const PLUGIN_FUNCTION = 'function';
136 : const PLUGIN_BLOCK = 'block';
137 : const PLUGIN_COMPILER = 'compiler';
138 : const PLUGIN_MODIFIER = 'modifier';
139 : const PLUGIN_MODIFIERCOMPILER = 'modifiercompiler';
140 : /**
141 : * unassigend template variable handling
142 : */
143 : const UNASSIGNED_IGNORE = 0;
144 : const UNASSIGNED_NOTICE = 1;
145 : const UNASSIGNED_EXCEPTION = 2;
146 :
147 : /* * #@- */
148 :
149 : /**
150 : * assigned tpl vars
151 : * @internal
152 : */
153 : public $tpl_vars = null;
154 :
155 : /**
156 : * assigned global tpl vars
157 : * @internal
158 : */
159 : public static $global_tpl_vars = null;
160 :
161 : /**
162 : * error handler returned by set_error_hanlder() in Smarty::muteExpectedErrors()
163 : * @internal
164 : */
165 : public static $_previous_error_handler = null;
166 :
167 : /**
168 : * contains directories outside of SMARTY_DIR that are to be muted by muteExpectedErrors()
169 : * @internal
170 : */
171 : public static $_muted_directories = array();
172 :
173 : /**
174 : * contains callbacks to invoke on events
175 : * @internal
176 : */
177 : public static $_callbacks = array();
178 :
179 : /**
180 : * Flag denoting if Multibyte String functions are available
181 : */
182 : public static $_MBSTRING = SMARTY_MBSTRING;
183 :
184 : /**
185 : * The character set to adhere to (e.g. "UTF-8")
186 : */
187 : public static $_CHARSET = SMARTY_RESOURCE_CHAR_SET;
188 :
189 : /**
190 : * The date format to be used internally
191 : * (accepts date() and strftime())
192 : */
193 : public static $_DATE_FORMAT = SMARTY_RESOURCE_DATE_FORMAT;
194 :
195 : /**
196 : * Flag denoting if PCRE should run in UTF-8 mode
197 : */
198 : public static $_UTF8_MODIFIER = 'u';
199 :
200 2 : /**
201 : * Flag denoting if operating system is windows
202 : */
203 : public static $_IS_WINDOWS = false;
204 : /** #@+
205 : * variables
206 : */
207 :
208 : /**
209 : * auto literal on delimiters with whitspace
210 : * @var boolean
211 : * @link http://www.smarty.net/docs/en/variable.auto.literal.tpl
212 : */
213 : public $auto_literal = true;
214 :
215 : /**
216 7 : * flag if template specific objs shall be cached during processing
217 : * @var mixed
218 : */
219 : public $cache_objs = true;
220 :
221 : /**
222 : * display error on not assigned variables
223 : * @var integer
224 : * @link <missing>
225 : * @uses UNASSIGNED_IGNORE as possible value
226 : * @uses UNASSIGNED_NOTICE as possible value
227 : * @uses UNASSIGNED_EXCEPTION as possible value
228 : */
229 : public $error_unassigned = self::UNASSIGNED_IGNORE;
230 :
231 : /**
232 : * look up relative filepaths in include_path
233 : * @var boolean
234 : * @link http://www.smarty.net/docs/en/variable.use.include.path.tpl
235 : */
236 : public $use_include_path = false;
237 :
238 : /**
239 : * template directory
240 : * @var array
241 : * @link http://www.smarty.net/docs/en/variable.template.dir.tpl
242 : */
243 : private $template_dir = array();
244 :
245 : /**
246 : * joined template directory string used in cache keys
247 : * @var string
248 : * @internal
249 : */
250 : public $joined_template_dir = null;
251 :
252 : /**
253 : * joined config directory string used in cache keys
254 : * @var string
255 : * @internal
256 : */
257 : public $joined_config_dir = null;
258 :
259 : /**
260 : * default template handler
261 : * @var callable
262 : * @link http://www.smarty.net/docs/en/variable.default.template.handler.func.tpl
263 : */
264 : public $default_template_handler_func = null;
265 :
266 : /**
267 : * default config handler
268 : * @var callable
269 : * @link http://www.smarty.net/docs/en/variable.default.config.handler.func.tpl
270 : */
271 : public $default_config_handler_func = null;
272 :
273 : /**
274 : * default plugin handler
275 : * @var callable
276 : * @link <missing>
277 : */
278 68 : public $default_plugin_handler_func = null;
279 :
280 : /**
281 : * default variable handler
282 : * @var callable
283 : * @link <missing>
284 : */
285 : public $default_variable_handler_func = null;
286 :
287 : /**
288 : * default config variable handler
289 : * @var callable
290 : * @link <missing>
291 : */
292 : public $default_config_variable_handler_func = null;
293 :
294 : /**
295 : * compile directory
296 : * @var string
297 : * @link http://www.smarty.net/docs/en/variable.compile.dir.tpl
298 : */
299 : private $compile_dir = null;
300 :
301 : /**
302 : * plugins directory
303 : * @var array
304 : * @link http://www.smarty.net/docs/en/variable.plugins.dir.tpl
305 : */
306 : private $plugins_dir = array();
307 :
308 : /**
309 : * cache directory
310 : * @var string
311 : * @link http://www.smarty.net/docs/en/variable.cache.dir.tpl
312 : */
313 : private $cache_dir = null;
314 :
315 : /**
316 : * config directory
317 : * @var array
318 : * @link http://www.smarty.net/docs/en/variable.fooobar.tpl
319 : */
320 : private $config_dir = array();
321 :
322 : /**
323 : * disable core plugins in {@link loadPlugin()}
324 : * @var boolean
325 : * @link <missing>
326 : */
327 : public $disable_core_plugins = false;
328 :
329 : /**
330 : * force template compiling?
331 : * @var boolean
332 : * @link http://www.smarty.net/docs/en/variable.force.compile.tpl
333 : */
334 : public $force_compile = false;
335 :
336 : /**
337 : * check template for modifications?
338 : * @var int
339 : * @link http://www.smarty.net/docs/en/variable.compile.check.tpl
340 : * @uses COMPILECHECK_OFF as possible value
341 : * @uses COMPILECHECK_ON as possible value
342 : * @uses COMPILECHECK_CACHEMISS as possible value
343 : */
344 : public $compile_check = self::COMPILECHECK_ON;
345 :
346 : /**
347 : * use sub dirs for compiled/cached files?
348 : * @var boolean
349 : * @link http://www.smarty.net/docs/en/variable.use.sub.dirs.tpl
350 : */
351 : public $use_sub_dirs = false;
352 :
353 : /**
354 : * allow ambiguous resources (that are made unique by the resource handler)
355 : * @var boolean
356 : */
357 : public $allow_ambiguous_resources = false;
358 :
359 : /*
360 : * caching enabled
361 : * @var integer
362 : * @link http://www.smarty.net/docs/en/variable.caching.tpl
363 : * @uses CACHING_OFF as possible value
364 : * @uses CACHING_LIFETIME_CURRENT as possible value
365 : * @uses CACHING_LIFETIME_SAVED as possible value
366 : */
367 : public $caching = self::CACHING_OFF;
368 :
369 : /**
370 : * merge compiled includes
371 : * @var boolean
372 : * @link http://www.smarty.net/docs/en/variable.merge.compiled.includes.tpl
373 : */
374 : public $merge_compiled_includes = false;
375 :
376 : /**
377 : * cache lifetime in seconds
378 : * @var integer
379 : * @link http://www.smarty.net/docs/en/variable.cache.lifetime.tpl
380 : */
381 : public $cache_lifetime = 3600;
382 :
383 : /**
384 : * force cache file creation
385 : * @var boolean
386 : * @link http://www.smarty.net/docs/en/variable.force.cache.tpl
387 : */
388 : public $force_cache = false;
389 :
390 : /**
391 : * Set this if you want different sets of cache files for the same
392 : * templates.
393 : * @var string
394 : * @link http://www.smarty.net/docs/en/variable.cache.id.tpl
395 : */
396 : public $cache_id = null;
397 :
398 : /**
399 : * Save last setting of cache_id
400 : * @var string
401 : */
402 : public $_tpl_old_cache_id = null;
403 :
404 : /**
405 : * Set this if you want different sets of compiled files for the same
406 : * templates.
407 : * @var string
408 : * @link http://www.smarty.net/docs/en/variable.compile.id.tpl
409 : */
410 : public $compile_id = null;
411 :
412 : /**
413 : * Save last setting of compile_id
414 : * @var string
415 : */
416 : public $_tpl_old_compile_id = null;
417 :
418 : /**
419 : * template left-delimiter
420 : * @var string
421 : * @link http://www.smarty.net/docs/en/variable.left.delimiter.tpl
422 : */
423 : public $left_delimiter = "{";
424 :
425 : /**
426 : * template right-delimiter
427 : * @var string
428 : * @link http://www.smarty.net/docs/en/variable.right.delimiter.tpl
429 : */
430 : public $right_delimiter = "}";
431 : /* * #@+
432 : * security
433 : */
434 :
435 : /**
436 : * class name
437 : *
438 : * This should be instance of Smarty_Security.
439 : * @var string
440 : * @see Smarty_Security
441 : * @link <missing>
442 : */
443 : public $security_class = 'Smarty_Security';
444 :
445 : /**
446 : * implementation of security class
447 : * @var Smarty_Security
448 : * @see Smarty_Security
449 : * @link <missing>
450 : */
451 : public $security_policy = null;
452 :
453 : /**
454 : * controls handling of PHP-blocks
455 : * @var integer
456 : * @link http://www.smarty.net/docs/en/variable.php.handling.tpl
457 : * @uses PHP_PASSTHRU as possible value
458 : * @uses PHP_QUOTE as possible value
459 : * @uses PHP_REMOVE as possible value
460 : * @uses PHP_ALLOW as possible value
461 : */
462 : public $php_handling = self::PHP_PASSTHRU;
463 :
464 : /**
465 : * controls if the php template file resource is allowed
466 : * @var boolean
467 : * @link http://www.smarty.net/docs/en/api.variables.tpl#variable.allow.php.templates
468 : */
469 : public $allow_php_templates = false;
470 :
471 : /**
472 : * Should compiled-templates be prevented from being called directly?
473 : *
474 : * {@internal
475 : * Currently used by Smarty_Internal_Template_ only.
476 : * }}
477 : *
478 : * @var boolean
479 : * @link http://www.smarty.net/docs/en/variable.direct.access.security.tpl
480 : */
481 : public $direct_access_security = true;
482 : /* * #@- */
483 :
484 : /**
485 : * debug mode
486 : *
487 : * Setting this to true enables the debug-console.
488 : *
489 : * @var boolean
490 : * @link http://www.smarty.net/docs/en/variable.debugging.tpl
491 : */
492 : public $debugging = false;
493 :
494 : /**
495 : * This determines if debugging is enable-able from the browser.
496 : * <ul>
497 : * <li>NONE => no debugging control allowed</li>
498 : * <li>URL => enable debugging when SMARTY_DEBUG is found in the URL.</li>
499 : * </ul>
500 : * @var string
501 : * @link http://www.smarty.net/docs/en/variable.debugging.ctrl.tpl
502 : */
503 : public $debugging_ctrl = 'NONE';
504 :
505 : /**
506 : * Name of debugging URL-param.
507 : * Only used when $debugging_ctrl is set to 'URL'.
508 : * The name of the URL-parameter that activates debugging.
509 : * @var string
510 : * @link http://www.smarty.net/docs/en/variable.smarty.debug.id.tpl
511 : */
512 : public $smarty_debug_id = 'SMARTY_DEBUG';
513 :
514 : /**
515 : * Path of debug template.
516 : * @var string
517 : * @link http://www.smarty.net/docs/en/variable.debugtpl_obj.tpl
518 : */
519 : public $debug_tpl = null;
520 :
521 : /**
522 : * Path of error template.
523 : * @var string
524 : */
525 : public $error_tpl = null;
526 :
527 : /**
528 : * enable error processing
529 : * @var boolean
530 : */
531 : public $error_processing = true;
532 :
533 : /**
534 : * When set, smarty uses this value as error_reporting-level.
535 : * @var integer
536 : * @link http://www.smarty.net/docs/en/variable.error.reporting.tpl
537 : */
538 : public $error_reporting = null;
539 :
540 : /**
541 : * Internal flag for getTags()
542 : * @var boolean
543 : * @internal
544 : */
545 : public $get_used_tags = false;
546 :
547 : /* * #@+
548 : * config var settings
549 : */
550 :
551 : /**
552 : * Controls whether variables with the same name overwrite each other.
553 : * @var boolean
554 : * @link http://www.smarty.net/docs/en/variable.config.overwrite.tpl
555 : */
556 : public $config_overwrite = true;
557 :
558 : /**
559 : * Controls whether config values of on/true/yes and off/false/no get converted to boolean.
560 : * @var boolean
561 : * @link http://www.smarty.net/docs/en/variable.config.booleanize.tpl
562 : */
563 : public $config_booleanize = true;
564 :
565 : /**
566 : * Controls whether hidden config sections/vars are read from the file.
567 : * @var boolean
568 : * @link http://www.smarty.net/docs/en/variable.config.read.hidden.tpl
569 : */
570 : public $config_read_hidden = false;
571 :
572 : /* * #@- */
573 :
574 : /* * #@+
575 : * resource locking
576 : */
577 :
578 : /**
579 : * locking concurrent compiles
580 : * @var boolean
581 : * @link http://www.smarty.net/docs/en/variable.compile.locking.tpl
582 : */
583 : public $compile_locking = true;
584 :
585 : /**
586 : * Controls whether cache resources should emply locking mechanism
587 : * @var boolean
588 : * @link http://www.smarty.net/docs/en/variable.cache.locking.tpl
589 : */
590 : public $cache_locking = false;
591 :
592 : /**
593 : * seconds to wait for acquiring a lock before ignoring the write lock
594 : * @var float
595 : * @link http://www.smarty.net/docs/en/variable.locking.timeout.tpl
596 : */
597 : public $locking_timeout = 10;
598 :
599 : /* * #@- */
600 :
601 : /**
602 : * global template functions
603 : * @var array
604 : * @internal
605 : */
606 : public $template_functions = array();
607 :
608 : /**
609 : * resource types provided by the core
610 : * @var array
611 : */
612 : protected static $system_resources = array(
613 : Smarty::SOURCE => array(
614 : 'file' => true,
615 : 'string' => true,
616 : 'extends' => true,
617 : 'stream' => true,
618 : 'eval' => true,
619 : 'php' => true,
620 : ),
621 : Smarty::COMPILED => array(
622 : 'file' => true,
623 : ),
624 : Smarty::CACHE => array(
625 : 'file' => true,
626 : )
627 : );
628 :
629 : /**
630 : * resource type used if none given
631 : * Must be an valid key of $registered_resources.
632 : * @var string
633 : * @link http://www.smarty.net/docs/en/variable.default.resource.type.tpl
634 : */
635 : public $default_resource_type = 'file';
636 :
637 : /**
638 : * caching type
639 : * Must be an element of $cache_resource_types.
640 : * @var string
641 : * @link http://www.smarty.net/docs/en/variable.caching.type.tpl
642 : */
643 : public $caching_type = 'file';
644 :
645 : /**
646 : * compiled type
647 : * Must be an element of $cache_resource_types.
648 : * @var string
649 : * @link http://www.smarty.net/docs/en/variable.caching.type.tpl
650 : */
651 : public $compiled_type = 'file';
652 :
653 : /**
654 : * internal config properties
655 : * @var array
656 : * @internal
657 : */
658 : public $properties = array();
659 :
660 : /**
661 : * config type
662 : * @var string
663 : * @link http://www.smarty.net/docs/en/variable.default.config.type.tpl
664 : */
665 : public $default_config_type = 'file';
666 :
667 : /**
668 : * cached template objects
669 : * @var array
670 : * @internal
671 : */
672 : public static $template_objects = array();
673 :
674 : /**
675 : * cached resource objects
676 : * @var array
677 : * @internal
678 : */
679 : public static $resource_cache = array();
680 :
681 : /**
682 : * check If-Modified-Since headers
683 : * @var boolean
684 : * @link http://www.smarty.net/docs/en/variable.cache.modified.check.tpl
685 : */
686 : public $cache_modified_check = false;
687 :
688 : /**
689 : * registered plugins
690 : * @var array
691 : * @internal
692 : */
693 : public $registered_plugins = array();
694 :
695 : /**
696 : * plugin search order
697 : * @var array
698 : * @link <missing>
699 : */
700 : public $plugin_search_order = array('function', 'block', 'compiler', 'class');
701 :
702 : /**
703 : * registered objects
704 : * @var array
705 : * @internal
706 : */
707 : public $registered_objects = array();
708 :
709 : /**
710 : * registered classes
711 : * @var array
712 : * @internal
713 : */
714 : public $registered_classes = array();
715 :
716 : /**
717 : * registered filters
718 : * @var array
719 : * @internal
720 : */
721 : public $registered_filters = array();
722 :
723 : /**
724 : * registered resources
725 : * @var array
726 : * @internal
727 : */
728 : public $registered_resources = array();
729 :
730 : /**
731 : * autoload filter
732 : * @var array
733 : * @link http://www.smarty.net/docs/en/variable.autoload.filters.tpl
734 : */
735 : public $autoload_filters = array();
736 :
737 : /**
738 : * default modifier
739 : * @var array
740 : * @link http://www.smarty.net/docs/en/variable.default.modifiers.tpl
741 : */
742 : public $default_modifiers = array();
743 :
744 : /**
745 : * autoescape variable output
746 : * @var boolean
747 : * @link http://www.smarty.net/docs/en/variable.escape.html.tpl
748 : */
749 : public $escape_html = false;
750 :
751 : /**
752 : * global internal smarty vars
753 : * @var array
754 : */
755 : public static $_smarty_vars = array();
756 :
757 : /**
758 : * start time for execution time calculation
759 : * @var integer
760 : * @internal
761 : */
762 : public $start_time = 0;
763 :
764 : /**
765 : * default file permissions (octal)
766 : * @var integer
767 : * @internal
768 : */
769 : public $_file_perms = 0644;
770 :
771 : /**
772 : * default dir permissions (octal)
773 : * @var integer
774 : * @internal
775 : */
776 : public $_dir_perms = 0771;
777 :
778 : /**
779 : * block tag hierarchy
780 : * @var array
781 : * @internal
782 : */
783 : public $_tag_stack = array();
784 :
785 : /**
786 : * required by the compiler for BC
787 : * @var string
788 : * @internal
789 : */
790 : public $_current_file = null;
791 :
792 : /**
793 : * internal flag to enable parser debugging
794 : * @var boolean
795 : * @internal
796 : */
797 : public $_parserdebug = false;
798 :
799 : /* * #@- */
800 :
801 : /* * #@+
802 : * template properties
803 : */
804 :
805 : /**
806 : * individually cached subtemplates
807 : * @var array
808 : */
809 : public $cached_subtemplates = array();
810 :
811 : /**
812 : * Template resource
813 : * @var string
814 : * @internal
815 : */
816 : public $template_resource = null;
817 :
818 : /**
819 : * flag set when nocache code sections are executed
820 : * @var boolean
821 : * @internal
822 : */
823 : public $is_nocache = false;
824 :
825 : /**
826 : * root template of hierarchy
827 : *
828 : * @var Smarty
829 : */
830 : public $rootTemplate = null;
831 :
832 : /**
833 : * {block} tags of this template
834 : *
835 : * @var array
836 : * @internal
837 : */
838 : public $block = array();
839 :
840 : /**
841 : * variable filters
842 : * @var array
843 : * @internal
844 : */
845 : public $variable_filters = array();
846 :
847 : /**
848 : * optional log of tag/attributes
849 : * @var array
850 : * @internal
851 : */
852 : public $used_tags = array();
853 :
854 : /**
855 : * internal flag to allow relative path in child template blocks
856 : * @var boolean
857 : * @internal
858 : */
859 : public $allow_relative_path = false;
860 :
861 : /**
862 : * flag this is inheritance child template
863 : *
864 : * @var bool
865 : */
866 : public $is_inheritance_child = false;
867 :
868 : /**
869 : * internal capture runtime stack
870 : * @var array
871 : * @internal
872 : */
873 :
874 : public $_capture_stack = array(0 => array());
875 :
876 : /**
877 : * Pointer to subtemplate with template functions
878 : * @var object Smarty_Template_Class
879 : * @internal
880 : */
881 : public $template_function_chain = null;
882 :
883 : /**
884 : * $compiletime_options
885 : * value is computed of the compiletime options relevant for config files
886 : * $config_read_hidden
887 : * $config_booleanize
888 : * $config_overwrite
889 : *
890 : * @var int
891 : */
892 : public $compiletime_options = 0;
893 :
894 : /*
895 : * Source object in case of clone by createTemplate()
896 : * @var Smarty_Resource
897 : */
898 : public $source = null;
899 :
900 : /* * #@- */
901 :
902 : /**
903 : * Initialize new Smarty object
904 : *
905 : */
906 : public function __construct()
907 : {
908 0 : $this->usage = self::IS_SMARTY;
909 : // create variable scope for Smarty root
910 0 : $this->tpl_vars = new Smarty_Variable_Scope($this, null, self::IS_SMARTY, 'Smarty root');
911 0 : self::$global_tpl_vars = new stdClass;
912 : // PHP options
913 0 : if (is_callable('mb_internal_encoding')) {
914 0 : mb_internal_encoding(self::$_CHARSET);
915 0 : }
916 0 : $this->start_time = microtime(true);
917 : // set default dirs
918 0 : $this->setTemplateDir('.' . DS . 'templates' . DS)
919 0 : ->setCompileDir('.' . DS . 'templates_c' . DS)
920 0 : ->setPluginsDir(SMARTY_PLUGINS_DIR)
921 0 : ->setCacheDir('.' . DS . 'cache' . DS)
922 0 : ->setConfigDir('.' . DS . 'configs' . DS);
923 :
924 0 : $this->debug_tpl = 'file:' . dirname(__FILE__) . '/debug.tpl';
925 0 : $this->error_tpl = 'file:' . dirname(__FILE__) . '/error.tpl';
926 0 : if (isset($_SERVER['SCRIPT_NAME'])) {
927 0 : $this->assignGlobal('SCRIPT_NAME', $_SERVER['SCRIPT_NAME']);
928 0 : }
929 0 : }
930 :
931 : /**
932 : * fetches a rendered Smarty template
933 : *
934 : * @api
935 : * @param string $template the resource handle of the template file or template object
936 : * @param mixed $cache_id cache id to be used with this template
937 : * @param mixed $compile_id compile id to be used with this template
938 : * @param Smarty $parent next higher level of Smarty variables
939 : * @param bool $display true: display, false: fetch
940 : * @param bool $no_output_filter if true do not run output filter
941 : * @param null $data
942 : * @param int $scope_type
943 : * @param null $caching
944 : * @param null|int $cache_lifetime
945 : * @param null| Smarty_Variable_Scope $_scope
946 : * @throws Smarty_Exception
947 : * @throws Smarty_Exception_Runtime
948 : * @return string rendered template output
949 : */
950 :
951 : public function fetch($template = null, $cache_id = null, $compile_id = null, $parent = null, $display = false, $no_output_filter = false, $data = null, $scope_type = Smarty::SCOPE_LOCAL, $caching = null, $cache_lifetime = null, $_scope = null)
952 : {
953 954 : if ($template === null && ($this->usage == self::IS_TEMPLATE || $this->usage == self::IS_CONFIG)) {
954 132 : $template = $this;
955 132 : }
956 954 : if (!empty($cache_id) && is_object($cache_id)) {
957 1 : $parent = $cache_id;
958 1 : $cache_id = null;
959 1 : }
960 954 : if ($parent === null && (!($this->usage == self::IS_TEMPLATE || $this->usage == self::IS_CONFIG) || is_string($template))) {
961 824 : $parent = $this;
962 824 : }
963 :
964 954 : if (is_object($template)) {
965 : // get source from template clone
966 703 : $source = $template->source;
967 703 : $tpl_obj = $template;
968 703 : } else {
969 : //get source object from cache or create new one
970 265 : $source = $this->_getSourceObj($template);
971 258 : $tpl_obj = $this;
972 : }
973 :
974 947 : if (isset($tpl_obj->error_reporting)) {
975 11 : $_smarty_old_error_level = error_reporting($tpl_obj->error_reporting);
976 11 : }
977 : // check URL debugging control
978 947 : if (!$tpl_obj->debugging && $tpl_obj->debugging_ctrl == 'URL') {
979 0 : Smarty_Debug::checkURLDebug($tpl_obj);
980 0 : }
981 :
982 : // checks if template exists
983 947 : if (!$source->exists) {
984 5 : $msg = "Unable to load template '{$source->type}:{$source->name}'";
985 5 : if ($parent && ($parent->usage == self::IS_TEMPLATE || $parent->usage == self::IS_CONFIG)) {
986 0 : throw new Smarty_Exception_Runtime($msg, $source);
987 : } else {
988 5 : throw new Smarty_Exception($msg);
989 : }
990 : }
991 : // disable caching for evaluated code
992 945 : $caching = $source->recompiled ? false : $tpl_obj->caching;
993 945 : $compile_id = isset($compile_id) ? $compile_id : $tpl_obj->compile_id;
994 945 : $cache_id = isset($cache_id) ? $cache_id : $tpl_obj->cache_id;
995 :
996 945 : if ($caching == self::CACHING_LIFETIME_CURRENT || $caching == self::CACHING_LIFETIME_SAVED) {
997 98 : $browser_cache_valid = false;
998 98 : $cached_obj = $tpl_obj->_loadCached($source, $compile_id, $cache_id, $caching);
999 98 : $_output = $cached_obj->getRenderedTemplate($tpl_obj, $_scope, $scope_type, $data, $no_output_filter, $display);
1000 68 : if ($_output === true) {
1001 0 : $browser_cache_valid = true;
1002 0 : }
1003 68 : } else {
1004 847 : if ($source->uncompiled) {
1005 1 : $_output = $source->getRenderedTemplate($tpl_obj, $_scope, $scope_type, $data);
1006 0 : } else {
1007 : // $content_obj = $tpl_obj->_getCompiledTemplate($source, $compile_id);
1008 : // $_output = $content_obj->getRenderedTemplate($tpl_obj, $_scope, $scope_type, $data, $no_output_filter);
1009 846 : $compiled_obj = $tpl_obj->_loadCompiled($source, $compile_id);
1010 845 : $_output = $compiled_obj->getRenderedTemplate($tpl_obj, $_scope, $scope_type, $data, $no_output_filter);
1011 : }
1012 : }
1013 819 : if (isset($tpl_obj->error_reporting)) {
1014 11 : error_reporting($_smarty_old_error_level);
1015 11 : }
1016 :
1017 819 : if (!$tpl_obj->cache_objs) {
1018 0 : $tpl_obj->_deleteTemplateObj($tpl_obj);
1019 0 : }
1020 :
1021 : // display or fetch
1022 819 : if ($display) {
1023 4 : if ($tpl_obj->caching && $tpl_obj->cache_modified_check) {
1024 1 : if (!$browser_cache_valid) {
1025 : switch (PHP_SAPI) {
1026 1 : case 'cli':
1027 : if ( /* ^phpunit */
1028 1 : !empty($_SERVER['SMARTY_PHPUNIT_DISABLE_HEADERS']) /* phpunit$ */
1029 1 : ) {
1030 1 : $_SERVER['SMARTY_PHPUNIT_HEADERS'][] = 'Last-Modified: ' . gmdate('D, d M Y H:i:s', $tpl_obj->cached->timestamp) . ' GMT';
1031 1 : }
1032 1 : break;
1033 :
1034 0 : default:
1035 0 : header('Last-Modified: ' . gmdate('D, d M Y H:i:s', time()) . ' GMT');
1036 0 : break;
1037 0 : }
1038 1 : echo $_output;
1039 1 : }
1040 1 : } else {
1041 3 : echo $_output;
1042 : }
1043 : // debug output
1044 4 : if ($tpl_obj->debugging) {
1045 1 : Smarty_Debug::display_debug($tpl_obj);
1046 0 : }
1047 :
1048 3 : return;
1049 : } else {
1050 : // return output on fetch
1051 815 : return $_output;
1052 : }
1053 : }
1054 :
1055 : /**
1056 : * displays a Smarty template
1057 : *
1058 : * @api
1059 : * @param string $template the resource handle of the template file or template object
1060 : * @param mixed $cache_id cache id to be used with this template
1061 : * @param mixed $compile_id compile id to be used with this template
1062 : * @param object $parent next higher level of Smarty variables
1063 : */
1064 : public function display($template = null, $cache_id = null, $compile_id = null, $parent = null)
1065 : {
1066 : // display template
1067 4 : $this->fetch($template, $cache_id, $compile_id, $parent, true);
1068 3 : }
1069 :
1070 : /**
1071 : * test if cache is valid
1072 : *
1073 : * @api
1074 : * @param string|object $template the resource handle of the template file or template object
1075 : * @param mixed $cache_id cache id to be used with this template
1076 : * @param mixed $compile_id compile id to be used with this template
1077 : * @param object $parent next higher level of Smarty variables
1078 : * @return boolean cache status
1079 : */
1080 : public function isCached($template = null, $cache_id = null, $compile_id = null, $parent = null)
1081 : {
1082 43 : if (!($this->caching == self::CACHING_LIFETIME_CURRENT || $this->caching == self::CACHING_LIFETIME_SAVED)) {
1083 : // caching is disabled
1084 6 : return false;
1085 : }
1086 37 : if ($template === null && ($this->usage == self::IS_TEMPLATE || $this->usage == self::IS_CONFIG)) {
1087 17 : $template = $this;
1088 17 : }
1089 37 : if (is_object($template)) {
1090 : // get source from template clone
1091 36 : $source = $template->source;
1092 36 : $tpl_obj = $template;
1093 36 : } else {
1094 : //get source object from cache or create new one
1095 1 : $source = $this->_getSourceObj($template);
1096 1 : $tpl_obj = $this;
1097 : }
1098 37 : if ($source->recompiled) {
1099 : // recompiled source can't be cached
1100 1 : return false;
1101 : }
1102 36 : $cached_obj = $tpl_obj->_loadCached($source, isset($compile_id) ? $compile_id : $tpl_obj->compile_id,
1103 36 : isset($cache_id) ? $cache_id : $tpl_obj->cache_id, $this->caching);
1104 36 : if (!$cached_obj->exists || !$cached_obj->isValid) {
1105 : // cache does not exists or is outdated
1106 35 : return false;
1107 : } else {
1108 : // cache is valid
1109 1 : return true;
1110 : }
1111 : }
1112 :
1113 : /**
1114 : * creates a template object
1115 : *
1116 : * @api
1117 : * @param string $template_resource the resource handle of the template file
1118 : * @param mixed $cache_id cache id to be used with this template
1119 : * @param mixed $compile_id compile id to be used with this template
1120 : * @param object $parent next higher level of Smarty variables
1121 : * @param boolean $is_config flag that template will be for config files
1122 : * @throws Smarty_Exception
1123 : * @return Smarty template object
1124 : */
1125 : public function createTemplate($template_resource, $cache_id = null, $compile_id = null, $parent = null, $is_config = false)
1126 : {
1127 853 : if (!is_string($template_resource)) {
1128 0 : throw new Smarty_Exception('err6', $this);
1129 : }
1130 853 : if (!empty($cache_id) && (is_object($cache_id) || is_array($cache_id))) {
1131 16 : $parent = $cache_id;
1132 16 : $cache_id = null;
1133 16 : }
1134 853 : if (!empty($parent) && is_array($parent)) {
1135 1 : $data = $parent;
1136 1 : $parent = null;
1137 1 : } else {
1138 852 : $data = null;
1139 : }
1140 853 : $tpl_obj = clone $this;
1141 853 : $tpl_obj->usage = self::IS_TEMPLATE;
1142 853 : $tpl_obj->parent = $parent;
1143 853 : if (isset($cache_id)) {
1144 31 : $tpl_obj->cache_id = $cache_id;
1145 31 : }
1146 853 : if (isset($compile_id)) {
1147 53 : $tpl_obj->compile_id = $compile_id;
1148 53 : }
1149 853 : $tpl_obj->source = $this->_getSourceObj($template_resource, $is_config);
1150 825 : $tpl_obj->tpl_vars = new Smarty_Variable_Scope($tpl_obj, $parent, Smarty::IS_DATA, $template_resource);
1151 825 : if (isset($data)) {
1152 1 : foreach ($data as $varname => $value) {
1153 1 : $tpl_obj->tpl_vars->$varname = new Smarty_Variable($value);
1154 1 : }
1155 1 : }
1156 :
1157 825 : return $tpl_obj;
1158 : }
1159 :
1160 : /**
1161 : * returns cached template object, or creates a new one
1162 : *
1163 : * @api
1164 : * @param string $template_resource tenplate and resource name
1165 : * @param bool $is_config is source for config file
1166 : * @return Smarty_Resource source object
1167 : */
1168 : public function _getSourceObj($template_resource, $is_config = false)
1169 : {
1170 : // already in template cache?
1171 1093 : if ($this->allow_ambiguous_resources) {
1172 4 : $resource = $this->_loadHandler(self::SOURCE, $template_resource);
1173 4 : $_templateId = $resource->buildUniqueResourceName($this, $resourcename);
1174 0 : } else {
1175 1089 : $_templateId = ($is_config ? $this->joined_config_dir : $this->joined_template_dir) . '#' . $template_resource;
1176 : }
1177 1089 : if (isset($_templateId[150])) {
1178 38 : $_templateId = sha1($_templateId);
1179 38 : }
1180 1089 : if (isset(self::$template_objects[$_templateId])) {
1181 : // return cached template object
1182 43 : $source = self::$template_objects[$_templateId];
1183 43 : } else {
1184 : // create new source object
1185 1089 : $source = $this->_loadSource($template_resource, $is_config);
1186 : // cache template object under a unique ID
1187 : // do not cache eval resources
1188 1058 : if ($source->type != 'eval') {
1189 336 : self::$template_objects[$_templateId] = $source;
1190 336 : }
1191 : }
1192 :
1193 1058 : return $source;
1194 : }
1195 :
1196 : public function _deleteTemplateObj($tpl_obj = null)
1197 : {
1198 0 : if ($tpl_obj == null) {
1199 : //delete all cached objs
1200 0 : self::$template_objects = array();
1201 0 : }
1202 0 : foreach (self::$template_objects as $key => $foo) {
1203 0 : if ($tpl_obj == $foo['template']) {
1204 : // get rid of any thing which belong to this template
1205 0 : unset(self::$template_objects[$tpl_obj->source->unique_resource]);
1206 0 : unset(self::$template_objects[$key]);
1207 0 : }
1208 0 : }
1209 0 : }
1210 :
1211 : /**
1212 : * creates a data object
1213 : *
1214 : * @api
1215 : * @param Smarty|Smarty_Data|Smarty_Variable_Scope $parent next higher level of Smarty variables
1216 : * @param string $scope_name optional name of Smarty_Data object
1217 : * @return object Smarty_Data
1218 : */
1219 : public function createData($parent = null, $scope_name = 'Data unnamed')
1220 : {
1221 19 : return new Smarty_Data($this, $parent, $scope_name);
1222 : }
1223 :
1224 : /**
1225 : * Registers plugin to be used in templates
1226 : *
1227 : * @param string $type plugin type
1228 : * @param string $tag name of template tag
1229 : * @param callback $callback PHP callback to register
1230 : * @param boolean $cacheable if true (default) this fuction is cachable
1231 : * @param array $cache_attr caching attributes if any
1232 : * @return Smarty
1233 : * @throws Smarty_Exception when the plugin tag is invalid
1234 : */
1235 : public function registerPlugin($type, $tag, $callback, $cacheable = true, $cache_attr = null)
1236 : {
1237 1180 : if (isset($this->registered_plugins[$type][$tag])) {
1238 0 : throw new Smarty_Exception("registerPlugin(): Plugin tag \"{$tag}\" already registered");
1239 1180 : } elseif (!is_callable($callback)) {
1240 0 : throw new Smarty_Exception("registerPlugin(): Plugin \"{$tag}\" not callable");
1241 : } else {
1242 1180 : if (is_object($callback)) {
1243 9 : $callback = array($callback, '__invoke');
1244 9 : }
1245 1180 : $this->registered_plugins[$type][$tag] = array($callback, (bool) $cacheable, (array) $cache_attr);
1246 : }
1247 :
1248 1180 : return $this;
1249 : }
1250 :
1251 : /**
1252 : * Unregister Plugin
1253 : *
1254 : * @api
1255 : * @param string $type of plugin
1256 : * @param string $tag name of plugin
1257 : * @return Smarty
1258 : */
1259 : public function unregisterPlugin($type, $tag)
1260 : {
1261 12 : if (isset($this->registered_plugins[$type][$tag])) {
1262 5 : unset($this->registered_plugins[$type][$tag]);
1263 5 : }
1264 :
1265 12 : return $this;
1266 : }
1267 :
1268 : /**
1269 : * Registers a resource to fetch a template
1270 : *
1271 : * @api
1272 : * @param string $type name of resource type
1273 : * @param Smarty_Resource|array $callback or instance of Smarty_Resource, or array of callbacks to handle resource (deprecated)
1274 : * @return Smarty
1275 : */
1276 : public function registerResource($type, $callback)
1277 : {
1278 5 : $this->registered_resources[self::SOURCE][$type] = $callback instanceof Smarty_Resource ? $callback : array($callback, false);
1279 :
1280 5 : return $this;
1281 : }
1282 :
1283 : /**
1284 : * Unregisters a resource
1285 : *
1286 : * @api
1287 : * @param string $type name of resource type
1288 : * @return Smarty
1289 : */
1290 : public function unregisterResource($type)
1291 : {
1292 0 : if (isset($this->registered_resources[self::SOURCE][$type])) {
1293 0 : unset($this->registered_resources[self::SOURCE][$type]);
1294 0 : }
1295 :
1296 0 : return $this;
1297 : }
1298 :
1299 : /**
1300 : * Registers a cache resource to cache a template's output
1301 : *
1302 : * @api
1303 : * @param string $type name of cache resource type
1304 : * @param Smarty_Cache_Resource $callback instance of Smarty_Cache_Resource to handle output caching
1305 : * @return Smarty
1306 : */
1307 : public function registerCacheResource($type, $callback)
1308 : {
1309 17 : $this->registered_resources[self::CACHE][$type] = $callback instanceof Smarty_Cache_Resource ? $callback : array($callback, false);
1310 :
1311 17 : return $this;
1312 : }
1313 :
1314 : /**
1315 : * Unregisters a cache resource
1316 : *
1317 : * @api
1318 : * @param string $type name of cache resource type
1319 : * @return Smarty
1320 : */
1321 : public function unregisterCacheResource($type)
1322 : {
1323 0 : if (isset($this->registered_resources[self::CACHE][$type])) {
1324 0 : unset($this->registered_resources[self::CACHE][$type]);
1325 0 : }
1326 :
1327 0 : return $this;
1328 : }
1329 :
1330 : /**
1331 : * Registers static classes to be used in templates
1332 : *
1333 : * @api
1334 : * @param string $class_name name of class
1335 : * @param string $class_impl the referenced PHP class to register
1336 : * @throws Smarty_Exception
1337 : * @return Smarty
1338 : */
1339 : public function registerClass($class_name, $class_impl)
1340 : {
1341 : // test if exists
1342 5 : if (!class_exists($class_impl)) {
1343 0 : throw new Smarty_Exception("registerClass(): Undefined class \"{$class_impl}\"");
1344 : }
1345 : // register the class
1346 5 : $this->registered_classes[$class_name] = $class_impl;
1347 :
1348 5 : return $this;
1349 : }
1350 :
1351 : /**
1352 : * Registers a default plugin handler
1353 : *
1354 : * @api
1355 : * @param callable $callback class/method name
1356 : * @return Smarty
1357 : * @throws Smarty_Exception if $callback is not callable
1358 : */
1359 : public function registerDefaultPluginHandler($callback)
1360 : {
1361 10 : if (is_callable($callback)) {
1362 10 : $this->default_plugin_handler_func = $callback;
1363 10 : } else {
1364 0 : throw new Smarty_Exception("registerDefaultPluginHandler(): Invalid callback");
1365 : }
1366 :
1367 10 : return $this;
1368 : }
1369 :
1370 : /**
1371 : * Registers a default template handler
1372 : *
1373 : * @api
1374 : * @param callable $callback class/method name
1375 : * @return Smarty
1376 : * @throws Smarty_Exception if $callback is not callable
1377 : */
1378 : public function registerDefaultTemplateHandler($callback)
1379 : {
1380 3 : if (is_callable($callback)) {
1381 2 : $this->default_template_handler_func = $callback;
1382 2 : } else {
1383 1 : throw new Smarty_Exception("registerDefaultTemplateHandler(): Invalid callback");
1384 : }
1385 :
1386 2 : return $this;
1387 : }
1388 :
1389 : /**
1390 : * Registers a default variable handler
1391 : *
1392 : * @api
1393 : * @param callable $callback class/method name
1394 : * @return Smarty
1395 : * @throws Smarty_Exception if $callback is not callable
1396 : */
1397 : public function registerDefaultVariableHandler($callback)
1398 : {
1399 4 : if (is_callable($callback)) {
1400 4 : $this->default_variable_handler_func = $callback;
1401 4 : } else {
1402 0 : throw new Smarty_Exception("registerDefaultVariableHandler(): Invalid callback");
1403 : }
1404 :
1405 4 : return $this;
1406 : }
1407 :
1408 : /**
1409 : * Registers a default config variable handler
1410 : *
1411 : * @api
1412 : * @param callable $callback class/method name
1413 : * @return Smarty
1414 : * @throws Smarty_Exception if $callback is not callable
1415 : */
1416 : public function registerDefaultConfigVariableHandler($callback)
1417 : {
1418 4 : if (is_callable($callback)) {
1419 4 : $this->default_config_variable_handler_func = $callback;
1420 4 : } else {
1421 0 : throw new Smarty_Exception("registerDefaultConfigVariableHandler(): Invalid callback");
1422 : }
1423 :
1424 4 : return $this;
1425 : }
1426 :
1427 : /**
1428 : * Registers a default config handler
1429 : *
1430 : * @api
1431 : * @param callable $callback class/method name
1432 : * @return Smarty
1433 : * @throws Smarty_Exception if $callback is not callable
1434 : */
1435 : public function registerDefaultConfigHandler($callback)
1436 : {
1437 4 : if (is_callable($callback)) {
1438 3 : $this->default_config_handler_func = $callback;
1439 3 : } else {
1440 1 : throw new Smarty_Exception("registerDefaultConfigHandler(): Invalid callback");
1441 : }
1442 :
1443 3 : return $this;
1444 : }
1445 :
1446 : /**
1447 : * Registers a filter function
1448 : *
1449 : * @api
1450 : * @param string $type filter type
1451 : * @param callback $callback
1452 : * @throws Smarty_Exception
1453 : * @return Smarty
1454 : */
1455 : public function registerFilter($type, $callback)
1456 : {
1457 27 : if (!in_array($type, array('pre', 'post', 'output', 'variable'))) {
1458 0 : throw new Smarty_Exception("registerFilter(): Invalid filter type \"{$type}\"");
1459 : }
1460 27 : if (is_callable($callback)) {
1461 27 : if ($callback instanceof Closure) {
1462 4 : $this->registered_filters[$type][] = $callback;
1463 4 : } else {
1464 23 : if (is_object($callback)) {
1465 4 : $callback = array($callback, '__invoke');
1466 4 : }
1467 23 : $this->registered_filters[$type][$this->_getFilterName($callback)] = $callback;
1468 : }
1469 27 : } else {
1470 0 : throw new Smarty_Exception("registerFilter(): Invalid callback");
1471 : }
1472 :
1473 27 : return $this;
1474 : }
1475 :
1476 : /**
1477 : * Unregisters a filter function
1478 : *
1479 : * @api
1480 : * @param string $type filter type
1481 : * @param callback $callback
1482 : * @return Smarty
1483 : */
1484 : public function unregisterFilter($type, $callback)
1485 : {
1486 6 : if (!isset($this->registered_filters[$type])) {
1487 0 : return $this;
1488 : }
1489 6 : if ($callback instanceof Closure) {
1490 0 : foreach ($this->registered_filters[$type] as $key => $_callback) {
1491 0 : if ($callback === $_callback) {
1492 0 : unset($this->registered_filters[$type][$key]);
1493 :
1494 0 : return $this;
1495 : }
1496 0 : }
1497 0 : } else {
1498 6 : if (is_object($callback)) {
1499 0 : $callback = array($callback, '__invoke');
1500 0 : }
1501 6 : $name = $this->_getFilterName($callback);
1502 6 : if (isset($this->registered_filters[$type][$name])) {
1503 6 : unset($this->registered_filters[$type][$name]);
1504 6 : }
1505 : }
1506 :
1507 6 : return $this;
1508 : }
1509 :
1510 : /**
1511 : * Return internal filter name
1512 : *
1513 : * @internal
1514 : * @param callback $function_name
1515 : * @return string
1516 : */
1517 : public function _getFilterName($function_name)
1518 : {
1519 23 : if (is_array($function_name)) {
1520 12 : $_class_name = (is_object($function_name[0]) ?
1521 12 : get_class($function_name[0]) : $function_name[0]);
1522 :
1523 12 : return $_class_name . '_' . $function_name[1];
1524 : } else {
1525 11 : return $function_name;
1526 : }
1527 : }
1528 :
1529 : /**
1530 : * load a filter of specified type and name
1531 : *
1532 : * @api
1533 : * @param string $type filter type
1534 : * @param string $name filter name
1535 : * @throws Smarty_Exception
1536 : * @return bool
1537 : */
1538 : public function loadFilter($type, $name)
1539 : {
1540 5 : if (!in_array($type, array('pre', 'post', 'output', 'variable'))) {
1541 0 : throw new Smarty_Exception("loadFilter(): Invalid filter type \"{$type}\"");
1542 : }
1543 5 : $_plugin = "smarty_{$type}filter_{$name}";
1544 5 : $_filter_name = $_plugin;
1545 5 : if ($this->_loadPlugin($_plugin)) {
1546 5 : if (class_exists($_plugin, false)) {
1547 0 : $_plugin = array($_plugin, 'execute');
1548 0 : }
1549 5 : if (is_callable($_plugin)) {
1550 5 : $this->registered_filters[$type][$_filter_name] = $_plugin;
1551 :
1552 5 : return true;
1553 : }
1554 0 : }
1555 0 : throw new Smarty_Exception("loadFilter(): {$type}filter \"{$name}\" not callable");
1556 : }
1557 :
1558 : /**
1559 : * unload a filter of specified type and name
1560 : *
1561 : * @api
1562 : * @param string $type filter type
1563 : * @param string $name filter name
1564 : * @return Smarty
1565 : */
1566 : public function unloadFilter($type, $name)
1567 : {
1568 0 : $_filter_name = "smarty_{$type}filter_{$name}";
1569 0 : if (isset($this->registered_filters[$type][$_filter_name])) {
1570 0 : unset($this->registered_filters[$type][$_filter_name]);
1571 0 : }
1572 :
1573 0 : return $this;
1574 : }
1575 :
1576 : /**
1577 : * Check if a template resource exists
1578 : *
1579 : * @api
1580 : * @param string $template_resource template name
1581 : * @return boolean status
1582 : */
1583 : public function templateExists($template_resource)
1584 : {
1585 8 : $source = $this->_loadSource($template_resource);
1586 :
1587 6 : return $source->exists;
1588 : }
1589 :
1590 : /**
1591 : * Returns a single or all global variables
1592 : *
1593 : * @param string $varname variable name or null
1594 : * @return string variable value or or array of variables
1595 : */
1596 : public function getGlobal($varname = null)
1597 : {
1598 3 : if (isset($varname)) {
1599 2 : if (isset(self::$global_tpl_vars->{$varname}->value)) {
1600 2 : return self::$global_tpl_vars->{$varname}->value;
1601 : } else {
1602 0 : return '';
1603 : }
1604 : } else {
1605 1 : $_result = array();
1606 1 : foreach (self::$global_tpl_vars AS $key => $var) {
1607 1 : if (strpos($key, '___') !== 0) {
1608 1 : $_result[$key] = $var->value;
1609 1 : }
1610 1 : }
1611 :
1612 1 : return $_result;
1613 : }
1614 : }
1615 :
1616 : /**
1617 : * Empty cache folder
1618 : *
1619 : * @api
1620 : * @param integer $exp_time expiration time
1621 : * @param string $type resource type
1622 : * @return integer number of cache files deleted
1623 : */
1624 : public function clearAllCache($exp_time = null, $type = null)
1625 : {
1626 : // load cache resource and call clearAll
1627 156 : return Smarty_Cache_Resource::clearAllCache($this, $exp_time, $type);
1628 : }
1629 :
1630 : /**
1631 : * Empty cache for a specific template
1632 : *
1633 : * @api
1634 : * @param string $template_name template name
1635 : * @param string $cache_id cache id
1636 : * @param string $compile_id compile id
1637 : * @param integer $exp_time expiration time
1638 : * @param string $type resource type
1639 : * @return integer number of cache files deleted
1640 : */
1641 : public function clearCache($template_name = null, $cache_id = null, $compile_id = null, $exp_time = null, $type = null)
1642 : {
1643 21 : return Smarty_Cache_Resource::clearCache($template_name, $cache_id, $compile_id, $exp_time, $type, $this);
1644 : }
1645 :
1646 : /**
1647 : * Delete compiled template file
1648 : *
1649 : * @api
1650 : * @param string $resource_name template name
1651 : * @param string $compile_id compile id
1652 : * @param integer $exp_time expiration time
1653 : * @return integer number of template files deleted
1654 : */
1655 : public function clearCompiledTemplate($resource_name = null, $compile_id = null, $exp_time = null)
1656 : {
1657 132 : return Smarty_Compiled_Resource::clearCompiledTemplate($this, $resource_name, $compile_id, $exp_time, $this);
1658 : }
1659 :
1660 : /**
1661 : * Loads security class and enables security
1662 : *
1663 : * @api
1664 : * @param string|Smarty_Security $security_class if a string is used, it must be class-name
1665 : * @return Smarty current Smarty instance for chaining
1666 : * @throws Smarty_Exception when an invalid class name is provided
1667 : */
1668 : public function enableSecurity($security_class = null)
1669 : {
1670 1180 : Smarty_Security::enableSecurity($this, $security_class);
1671 :
1672 1180 : return $this;
1673 : }
1674 :
1675 : /**
1676 : * Disable security
1677 : *
1678 : * @api
1679 : * @return Smarty current Smarty instance for chaining
1680 : */
1681 : public function disableSecurity()
1682 : {
1683 83 : $this->security_policy = null;
1684 :
1685 83 : return $this;
1686 : }
1687 :
1688 : /**
1689 : * Set template directory
1690 : *
1691 : * @api
1692 : * @param string|array $template_dir directory(s) of template sources
1693 : * @return Smarty current Smarty instance for chaining
1694 : */
1695 : public function setTemplateDir($template_dir)
1696 : {
1697 1180 : $this->template_dir = array();
1698 1180 : foreach ((array) $template_dir as $k => $v) {
1699 1180 : $this->template_dir[$k] = rtrim($v, '/\\') . DS;
1700 1180 : }
1701 :
1702 1180 : $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir);
1703 :
1704 1180 : return $this;
1705 : }
1706 :
1707 : /**
1708 : * Add template directory(s)
1709 : *
1710 : * @api
1711 : * @param string|array $template_dir directory(s) of template sources
1712 : * @param string $key of the array element to assign the template dir to
1713 : * @return Smarty current Smarty instance for chaining
1714 : */
1715 : public function addTemplateDir($template_dir, $key = null)
1716 : {
1717 : // make sure we're dealing with an array
1718 36 : $this->template_dir = (array) $this->template_dir;
1719 :
1720 36 : if (is_array($template_dir)) {
1721 0 : foreach ($template_dir as $k => $v) {
1722 0 : if (is_int($k)) {
1723 : // indexes are not merged but appended
1724 0 : $this->template_dir[] = rtrim($v, '/\\') . DS;
1725 0 : } else {
1726 : // string indexes are overridden
1727 0 : $this->template_dir[$k] = rtrim($v, '/\\') . DS;
1728 : }
1729 0 : }
1730 36 : } elseif ($key !== null) {
1731 : // override directory at specified index
1732 13 : $this->template_dir[$key] = rtrim($template_dir, '/\\') . DS;
1733 13 : } else {
1734 : // append new directory
1735 34 : $this->template_dir[] = rtrim($template_dir, '/\\') . DS;
1736 : }
1737 36 : $this->joined_template_dir = join(DIRECTORY_SEPARATOR, $this->template_dir);
1738 :
1739 36 : return $this;
1740 : }
1741 :
1742 : /**
1743 : * Get template directories
1744 : *
1745 : * @api
1746 : * @param mixed $index of directory to get, null to get all
1747 : * @return array|string list of template directories, or directory of $index
1748 : */
1749 : public function getTemplateDir($index = null)
1750 : {
1751 306 : if ($index !== null) {
1752 17 : return isset($this->template_dir[$index]) ? $this->template_dir[$index] : null;
1753 : }
1754 :
1755 306 : return (array) $this->template_dir;
1756 : }
1757 :
1758 : /**
1759 : * Set config directory
1760 : *
1761 : * @api
1762 : * @param array|string $config_dir directory(s) of configuration sources
1763 : * @return Smarty current Smarty instance for chaining
1764 : */
1765 : public function setConfigDir($config_dir)
1766 : {
1767 1180 : $this->config_dir = array();
1768 1180 : foreach ((array) $config_dir as $k => $v) {
1769 1180 : $this->config_dir[$k] = rtrim($v, '/\\') . DS;
1770 1180 : }
1771 :
1772 1180 : $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir);
1773 :
1774 1180 : return $this;
1775 : }
1776 :
1777 : /**
1778 : * Add config directory(s)
1779 : *
1780 : * @api
1781 : * @param string|array $config_dir directory(s) of config sources
1782 : * @param string $key of the array element to assign the config dir to
1783 : * @return Smarty current Smarty instance for chaining
1784 : */
1785 : public function addConfigDir($config_dir, $key = null)
1786 : {
1787 : // make sure we're dealing with an array
1788 0 : $this->config_dir = (array) $this->config_dir;
1789 :
1790 0 : if (is_array($config_dir)) {
1791 0 : foreach ($config_dir as $k => $v) {
1792 0 : if (is_int($k)) {
1793 : // indexes are not merged but appended
1794 0 : $this->config_dir[] = rtrim($v, '/\\') . DS;
1795 0 : } else {
1796 : // string indexes are overridden
1797 0 : $this->config_dir[$k] = rtrim($v, '/\\') . DS;
1798 : }
1799 0 : }
1800 0 : } elseif ($key !== null) {
1801 : // override directory at specified index
1802 0 : $this->config_dir[$key] = rtrim($config_dir, '/\\') . DS;
1803 0 : } else {
1804 : // append new directory
1805 0 : $this->config_dir[] = rtrim($config_dir, '/\\') . DS;
1806 : }
1807 :
1808 0 : $this->joined_config_dir = join(DIRECTORY_SEPARATOR, $this->config_dir);
1809 :
1810 0 : return $this;
1811 : }
1812 :
1813 : /**
1814 : * Get config directory
1815 : *
1816 : * @api
1817 : * @param mixed $index of directory to get, null to get all
1818 : * @return array|string configuration directory
1819 : */
1820 : public function getConfigDir($index = null)
1821 : {
1822 271 : if ($index !== null) {
1823 1 : return isset($this->config_dir[$index]) ? $this->config_dir[$index] : null;
1824 : }
1825 :
1826 271 : return (array) $this->config_dir;
1827 : }
1828 :
1829 : /**
1830 : * Set plugins directory
1831 : *
1832 : * @api
1833 : * Adds {@link SMARTY_PLUGINS_DIR} if not specified
1834 : * @param string|array $plugins_dir directory(s) of plugins
1835 : * @return Smarty current Smarty instance for chaining
1836 : */
1837 : public function setPluginsDir($plugins_dir)
1838 : {
1839 1180 : $this->plugins_dir = array();
1840 1180 : foreach ((array) $plugins_dir as $k => $v) {
1841 1180 : $this->plugins_dir[$k] = rtrim($v, '/\\') . DS;
1842 1180 : }
1843 :
1844 1180 : return $this;
1845 : }
1846 :
1847 : /**
1848 : * Adds directory of plugin files
1849 : *
1850 : * @api
1851 : * @param string|array $plugins_dir plugin folder names
1852 : * @return Smarty current Smarty instance for chaining
1853 : */
1854 : public function addPluginsDir($plugins_dir)
1855 : {
1856 : // make sure we're dealing with an array
1857 46 : $this->plugins_dir = (array) $this->plugins_dir;
1858 :
1859 46 : if (is_array($plugins_dir)) {
1860 0 : foreach ($plugins_dir as $k => $v) {
1861 0 : if (is_int($k)) {
1862 : // indexes are not merged but appended
1863 0 : $this->plugins_dir[] = rtrim($v, '/\\') . DS;
1864 0 : } else {
1865 : // string indexes are overridden
1866 0 : $this->plugins_dir[$k] = rtrim($v, '/\\') . DS;
1867 : }
1868 0 : }
1869 0 : } else {
1870 : // append new directory
1871 46 : $this->plugins_dir[] = rtrim($plugins_dir, '/\\') . DS;
1872 : }
1873 :
1874 46 : $this->plugins_dir = array_unique($this->plugins_dir);
1875 :
1876 46 : return $this;
1877 : }
1878 :
1879 : /**
1880 : * Get plugin directories
1881 : *
1882 : * @api
1883 : * @return array list of plugin directories
1884 : */
1885 : public function getPluginsDir()
1886 : {
1887 256 : return (array) $this->plugins_dir;
1888 : }
1889 :
1890 : /**
1891 : * Set compile directory
1892 : *
1893 : * @api
1894 : * @param string $compile_dir directory to store compiled templates in
1895 : * @return Smarty current Smarty instance for chaining
1896 : */
1897 : public function setCompileDir($compile_dir)
1898 : {
1899 1180 : $this->compile_dir = rtrim($compile_dir, '/\\') . DS;
1900 1180 : if (!isset(self::$_muted_directories[$this->compile_dir])) {
1901 688 : self::$_muted_directories[$this->compile_dir] = null;
1902 688 : }
1903 :
1904 1180 : return $this;
1905 : }
1906 :
1907 : /**
1908 : * Get compiled directory
1909 : *
1910 : * @api
1911 : * @return string path to compiled templates
1912 : */
1913 : public function getCompileDir()
1914 : {
1915 990 : return $this->compile_dir;
1916 : }
1917 :
1918 : /**
1919 : * Set cache directory
1920 : *
1921 : * @api
1922 : * @param string $cache_dir directory to store cached templates in
1923 : * @return Smarty current Smarty instance for chaining
1924 : */
1925 : public function setCacheDir($cache_dir)
1926 : {
1927 1180 : $this->cache_dir = rtrim($cache_dir, '/\\') . DS;
1928 1180 : if (!isset(self::$_muted_directories[$this->cache_dir])) {
1929 688 : self::$_muted_directories[$this->cache_dir] = null;
1930 688 : }
1931 :
1932 1180 : return $this;
1933 : }
1934 :
1935 : /**
1936 : * Get cache directory
1937 : *
1938 : * @api
1939 : * @return string path of cache directory
1940 : */
1941 : public function getCacheDir()
1942 : {
1943 221 : return $this->cache_dir;
1944 : }
1945 :
1946 : /**
1947 : * Set default modifiers
1948 : *
1949 : * @api
1950 : * @param array|string $modifiers modifier or list of modifiers to set
1951 : * @return Smarty current Smarty instance for chaining
1952 : */
1953 : public function setDefaultModifiers($modifiers)
1954 : {
1955 0 : $this->default_modifiers = (array) $modifiers;
1956 :
1957 0 : return $this;
1958 : }
1959 :
1960 : /**
1961 : * Add default modifiers
1962 : *
1963 : * @api
1964 : * @param array|string $modifiers modifier or list of modifiers to add
1965 : * @return Smarty current Smarty instance for chaining
1966 : */
1967 : public function addDefaultModifiers($modifiers)
1968 : {
1969 0 : if (is_array($modifiers)) {
1970 0 : $this->default_modifiers = array_merge($this->default_modifiers, $modifiers);
1971 0 : } else {
1972 0 : $this->default_modifiers[] = $modifiers;
1973 : }
1974 :
1975 0 : return $this;
1976 : }
1977 :
1978 : /**
1979 : * Get default modifiers
1980 : *
1981 : * @api
1982 : * @return array list of default modifiers
1983 : */
1984 : public function getDefaultModifiers()
1985 : {
1986 0 : return $this->default_modifiers;
1987 : }
1988 :
1989 : /**
1990 : * Set autoload filters
1991 : *
1992 : * @param array $filters filters to load automatically
1993 : * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types
1994 : * @return Smarty current Smarty instance for chaining
1995 : */
1996 : public function setAutoloadFilters($filters, $type = null)
1997 : {
1998 0 : if ($type !== null) {
1999 0 : $this->autoload_filters[$type] = (array) $filters;
2000 0 : } else {
2001 0 : $this->autoload_filters = (array) $filters;
2002 : }
2003 :
2004 0 : return $this;
2005 : }
2006 :
2007 : /**
2008 : * Add autoload filters
2009 : *
2010 : * @api
2011 : * @param array $filters filters to load automatically
2012 : * @param string $type "pre", "output", … specify the filter type to set. Defaults to none treating $filters' keys as the appropriate types
2013 : * @return Smarty current Smarty instance for chaining
2014 : */
2015 : public function addAutoloadFilters($filters, $type = null)
2016 : {
2017 0 : if ($type !== null) {
2018 0 : if (!empty($this->autoload_filters[$type])) {
2019 0 : $this->autoload_filters[$type] = array_merge($this->autoload_filters[$type], (array) $filters);
2020 0 : } else {
2021 0 : $this->autoload_filters[$type] = (array) $filters;
2022 : }
2023 0 : } else {
2024 0 : foreach ((array) $filters as $key => $value) {
2025 0 : if (!empty($this->autoload_filters[$key])) {
2026 0 : $this->autoload_filters[$key] = array_merge($this->autoload_filters[$key], (array) $value);
2027 0 : } else {
2028 0 : $this->autoload_filters[$key] = (array) $value;
2029 : }
2030 0 : }
2031 : }
2032 :
2033 0 : return $this;
2034 : }
2035 :
2036 : /**
2037 : * Get autoload filters
2038 : *
2039 : * @api
2040 : * @param string $type type of filter to get autoloads for. Defaults to all autoload filters
2041 : * @return array array( 'type1' => array( 'filter1', 'filter2', … ) ) or array( 'filter1', 'filter2', …) if $type was specified
2042 : */
2043 : public function getAutoloadFilters($type = null)
2044 : {
2045 0 : if ($type !== null) {
2046 0 : return isset($this->autoload_filters[$type]) ? $this->autoload_filters[$type] : array();
2047 : }
2048 :
2049 0 : return $this->autoload_filters;
2050 : }
2051 :
2052 : /**
2053 : * return name of debugging template
2054 : *
2055 : * @api
2056 : * @return string
2057 : */
2058 : public function getDebugTemplate()
2059 : {
2060 0 : return $this->debug_tpl;
2061 : }
2062 :
2063 : /**
2064 : * set the debug template
2065 : *
2066 : * @api
2067 : * @param string $tpl_name
2068 : * @return Smarty current Smarty instance for chaining
2069 : * @throws Smarty_Exception if file is not readable
2070 : */
2071 : public function setDebugTemplate($tpl_name)
2072 : {
2073 0 : if (!is_readable($tpl_name)) {
2074 0 : throw new Smarty_Exception("setDebugTemplate(): Unknown file '{$tpl_name}'");
2075 : }
2076 0 : $this->debug_tpl = $tpl_name;
2077 :
2078 0 : return $this;
2079 : }
2080 :
2081 :
2082 : /**
2083 : * Takes unknown classes and loads plugin files for them
2084 : * class name format: Smarty_PluginType_PluginName
2085 : * plugin filename format: plugintype.pluginname.php
2086 : *
2087 : * @internal
2088 : * @param string $plugin_name class plugin name to load
2089 : * @param bool $check check if already loaded
2090 : * @throws Smarty_Exception
2091 : * @return string |boolean filepath of loaded file or false
2092 : */
2093 : public function _loadPlugin($plugin_name, $check = true)
2094 : {
2095 : // if function or class exists, exit silently (already loaded)
2096 376 : if ($check && (is_callable($plugin_name) || class_exists($plugin_name, false))) {
2097 96 : return true;
2098 : }
2099 : // Plugin name is expected to be: Smarty_[Type]_[Name]
2100 284 : $_name_parts = explode('_', $plugin_name, 3);
2101 : // class name must have three parts to be valid plugin
2102 : // count($_name_parts) < 3 === !isset($_name_parts[2])
2103 284 : if (!isset($_name_parts[2]) || strtolower($_name_parts[0]) !== 'smarty') {
2104 28 : throw new Smarty_Exception("loadPlugin(): Plugin {$plugin_name} is not a valid name format");
2105 : }
2106 : // plugin filename is expected to be: [type].[name].php
2107 256 : $_plugin_filename = "{$_name_parts[1]}.{$_name_parts[2]}.php";
2108 :
2109 :
2110 256 : $_stream_resolve_include_path = function_exists('stream_resolve_include_path');
2111 : // add SMARTY_PLUGINS_DIR if not present
2112 256 : $_plugins_dir = $this->getPluginsDir();
2113 256 : if (!$this->disable_core_plugins) {
2114 256 : $_plugins_dir[] = SMARTY_PLUGINS_DIR;
2115 256 : }
2116 :
2117 : // loop through plugin dirs and find the plugin
2118 256 : foreach ($_plugins_dir as $_plugin_dir) {
2119 : $names = array(
2120 256 : $_plugin_dir . $_plugin_filename,
2121 256 : $_plugin_dir . strtolower($_plugin_filename),
2122 256 : );
2123 256 : foreach ($names as $file) {
2124 256 : if (file_exists($file)) {
2125 201 : require_once($file);
2126 :
2127 201 : return $file;
2128 : }
2129 126 : if ($this->use_include_path && !preg_match('/^([\/\\\\]|[a-zA-Z]:[\/\\\\])/', $_plugin_dir)) {
2130 : // try PHP include_path
2131 0 : if ($_stream_resolve_include_path) {
2132 0 : $file = stream_resolve_include_path($file);
2133 0 : } else {
2134 0 : $file = Smarty_Misc_GetIncludePath::getIncludePath($file);
2135 : }
2136 0 : if ($file !== false) {
2137 0 : require_once($file);
2138 :
2139 0 : return $file;
2140 : }
2141 0 : }
2142 126 : }
2143 126 : }
2144 :
2145 : // no plugin loaded
2146 120 : return false;
2147 : }
2148 :
2149 : /**
2150 : * Compile all template files
2151 : *
2152 : * @api
2153 : * @param string $extension file extension
2154 : * @param bool $force_compile true to force recompile of all template
2155 : * @param int $time_limit time limit
2156 : * @param int $max_errors maximum number of errors
2157 : * @return integer number of template files recompiled
2158 : */
2159 : public function compileAllTemplates($extension = '.tpl', $force_compile = false, $time_limit = 0, $max_errors = null)
2160 : {
2161 0 : return Smarty_Misc_Utility::compileAllTemplates($extension, $force_compile, $time_limit, $max_errors, $this);
2162 : }
2163 :
2164 : /**
2165 : * Compile all config files
2166 : *
2167 : * @api
2168 : * @param string $extension file extension
2169 : * @param bool $force_compile force all to recompile
2170 : * @param int $time_limit
2171 : * @param int $max_errors
2172 : * @return integer number of template files recompiled
2173 : */
2174 : public function compileAllConfig($extension = '.conf', $force_compile = false, $time_limit = 0, $max_errors = null)
2175 : {
2176 0 : return Smarty_Misc_Utility::compileAllConfig($extension, $force_compile, $time_limit, $max_errors, $this);
2177 : }
2178 :
2179 : /**
2180 : * Return array of tag/attributes of all tags used by an template
2181 : *
2182 : * @api
2183 : * @param Smarty $template object
2184 : * @return array of tag/attributes
2185 : */
2186 : public function getTags(Smarty $template)
2187 : {
2188 0 : return Smarty_Misc_Utility::getTags($template);
2189 : }
2190 :
2191 : /**
2192 : * Run installation test
2193 : *
2194 : * @api
2195 : * @param array $errors Array to write errors into, rather than outputting them
2196 : * @return boolean true if setup is fine, false if something is wrong
2197 : */
2198 : public function testInstall(&$errors = null)
2199 : {
2200 0 : return Smarty_Misc_Utility::testInstall($this, $errors);
2201 : }
2202 :
2203 : /**
2204 : * Get Smarty Configuration Information
2205 : *
2206 : * @api
2207 : * @param boolean $html return formatted HTML, array else
2208 : * @param integer $flags see Smarty_Internal_Info constants
2209 : * @return string|array configuration information
2210 : */
2211 : public function info($html = true, $flags = 0)
2212 : {
2213 0 : $info = new Smarty_Internal_Info($this);
2214 :
2215 0 : return $html ? $info->getHtml($flags) : $info->getArray($flags);
2216 : }
2217 :
2218 : /**
2219 : * Error Handler to mute expected messages
2220 : *
2221 : * @api
2222 : * @link http://php.net/set_error_handler
2223 : * @param integer $errno Error level
2224 : * @param $errstr
2225 : * @param $errfile
2226 : * @param $errline
2227 : * @param $errcontext
2228 : * @return boolean
2229 : */
2230 : public static function mutingErrorHandler($errno, $errstr, $errfile, $errline, $errcontext)
2231 : {
2232 2 : $_is_muted_directory = false;
2233 :
2234 : // add the SMARTY_DIR to the list of muted directories
2235 2 : if (!isset(self::$_muted_directories[SMARTY_DIR])) {
2236 1 : $smarty_dir = realpath(SMARTY_DIR);
2237 1 : if ($smarty_dir !== false) {
2238 1 : self::$_muted_directories[SMARTY_DIR] = array(
2239 1 : 'file' => $smarty_dir,
2240 1 : 'length' => strlen($smarty_dir),
2241 : );
2242 1 : }
2243 1 : }
2244 :
2245 : // walk the muted directories and test against $errfile
2246 2 : foreach (self::$_muted_directories as $key => &$dir) {
2247 2 : if (!$dir) {
2248 : // resolve directory and length for speedy comparisons
2249 1 : $file = realpath($key);
2250 1 : if ($file === false) {
2251 : // this directory does not exist, remove and skip it
2252 0 : unset(self::$_muted_directories[$key]);
2253 0 : continue;
2254 : }
2255 : $dir = array(
2256 1 : 'file' => $file,
2257 1 : 'length' => strlen($file),
2258 1 : );
2259 1 : }
2260 2 : if (strpos($errfile, $dir['file']) === 0) {
2261 2 : $_is_muted_directory = true;
2262 2 : break;
2263 : }
2264 2 : }
2265 :
2266 : // pass to next error handler if this error did not occur inside SMARTY_DIR
2267 : // or the error was within smarty but masked to be ignored
2268 2 : if (!$_is_muted_directory || ($errno && $errno & error_reporting())) {
2269 2 : if (self::$_previous_error_handler) {
2270 2 : return call_user_func(self::$_previous_error_handler, $errno, $errstr, $errfile, $errline, $errcontext);
2271 : } else {
2272 0 : return false;
2273 : }
2274 : }
2275 2 : }
2276 :
2277 : /**
2278 : * Enable error handler to mute expected messages
2279 : *
2280 : * @api
2281 : * @return void
2282 : */
2283 : public static function muteExpectedErrors()
2284 : {
2285 : /*
2286 : error muting is done because some people implemented custom error_handlers using
2287 : http://php.net/set_error_handler and for some reason did not understand the following paragraph:
2288 :
2289 : It is important to remember that the standard PHP error handler is completely bypassed for the
2290 : error types specified by error_types unless the callback function returns FALSE.
2291 : error_reporting() settings will have no effect and your error handler will be called regardless -
2292 : however you are still able to read the current value of error_reporting and act appropriately.
2293 : Of particular note is that this value will be 0 if the statement that caused the error was
2294 : prepended by the @ error-control operator.
2295 :
2296 : Smarty deliberately uses @filemtime() over file_exists() and filemtime() in some places. Reasons include
2297 : - @filemtime() is almost twice as fast as using an additional file_exists()
2298 : - between file_exists() and filemtime() a possible race condition is opened,
2299 : which does not exist using the simple @filemtime() approach.
2300 : */
2301 2 : $error_handler = array('Smarty', 'mutingErrorHandler');
2302 2 : $previous = set_error_handler($error_handler);
2303 :
2304 : // avoid dead loops
2305 2 : if ($previous !== $error_handler) {
2306 2 : self::$_previous_error_handler = $previous;
2307 2 : }
2308 2 : }
2309 :
2310 : /**
2311 : * Disable error handler muting expected messages
2312 : *
2313 : * @api
2314 : * @return void
2315 : */
2316 : public static function unmuteExpectedErrors()
2317 : {
2318 2 : restore_error_handler();
2319 2 : }
2320 :
2321 : /**
2322 : * Identify and get top-level template instance
2323 : *
2324 : * @api
2325 : * @return Smarty root template object
2326 : */
2327 : public function findRootTemplate()
2328 : {
2329 1 : $tpl_obj = $this;
2330 1 : while ($tpl_obj->parent && ($tpl_obj->parent->usage == self::IS_TEMPLATE || $tpl_obj->parent->usage == self::IS_CONFIG)) {
2331 0 : if ($tpl_obj->rootTemplate) {
2332 0 : return $this->rootTemplate = $tpl_obj->rootTemplate;
2333 : }
2334 :
2335 0 : $tpl_obj = $tpl_obj->parent;
2336 0 : }
2337 :
2338 1 : return $this->rootTemplate = $tpl_obj;
2339 : }
2340 :
2341 : /**
2342 : * Save value to persistent cache storage
2343 : *
2344 : * @api
2345 : * @param string|array $key key to store data under, or array of key => values to store
2346 : * @param mixed $value value to store for $key, ignored if key is an array
2347 : * @return Smarty $this for chaining
2348 : */
2349 : public function assignCached($key, $value = null)
2350 : {
2351 1 : if (!$this->rootTemplate) {
2352 1 : $this->findRootTemplate();
2353 1 : }
2354 :
2355 1 : if (is_array($key)) {
2356 0 : foreach ($key as $_key => $_value) {
2357 0 : if ($_key !== '') {
2358 0 : $this->rootTemplate->properties['cachedValues'][$_key] = $_value;
2359 0 : }
2360 0 : }
2361 0 : } else {
2362 1 : if ($key !== '') {
2363 1 : $this->rootTemplate->properties['cachedValues'][$key] = $value;
2364 1 : }
2365 : }
2366 :
2367 1 : return $this;
2368 : }
2369 :
2370 : /**
2371 : * Get value from persistent cache storage
2372 : *
2373 : * @api
2374 : * @param string $key key of value to retrieve, null for all values (default)
2375 : * @return mixed value or array of values
2376 : */
2377 : public function getCachedVars($key = null)
2378 : {
2379 1 : if (!$this->rootTemplate) {
2380 0 : $this->findRootTemplate();
2381 0 : }
2382 :
2383 1 : if ($key === null) {
2384 0 : return isset($this->rootTemplate->properties['cachedValues']) ? $this->rootTemplate->properties['cachedValues'] : array();
2385 : }
2386 :
2387 1 : return isset($this->rootTemplate->properties['cachedValues'][$key]) ? $this->rootTemplate->properties['cachedValues'][$key] : null;
2388 : }
2389 :
2390 : /**
2391 : * clean up object pointer
2392 : *
2393 : */
2394 : public function cleanPointer()
2395 : {
2396 0 : unset($this->source, $this->compiled, $this->cached, $this->compiler, $this->must_compile);
2397 0 : $this->tpl_vars = $this->parent = $this->template_function_chain = $this->rootTemplate = null;
2398 0 : }
2399 :
2400 : /**
2401 : *
2402 : * @params string $template_resource template resource
2403 : * @param bool $is_config is source for config file
2404 : * @return Smarty_Resource
2405 : */
2406 : public function _loadSource($template_resource, $is_config = false)
2407 : {
2408 1097 : $source = $this->_loadHandler(self::SOURCE, $template_resource);
2409 1069 : $source->usage = $is_config ? self::IS_CONFIG : self::IS_TEMPLATE;
2410 1069 : $source->populate($this);
2411 :
2412 1064 : return $source;
2413 : }
2414 :
2415 : /**
2416 : *
2417 : * @params Smarty_Resource $source source resource
2418 : * @params mixed $compile_id compile id
2419 : * @params boolean $caching caching enabled ?
2420 : * @return Smarty_Template_Class
2421 : */
2422 : public function _getCompiledTemplate(Smarty_Resource $source, $compile_id, $caching = false)
2423 : {
2424 : // check runtime cache
2425 0 : $source_key = $source->uid;
2426 0 : $compiled_key = $compile_id ? $compile_id : '#null#';
2427 0 : if ($caching) {
2428 0 : $compiled_key .= '#caching';
2429 0 : }
2430 0 : if ($this->cache_objs) {
2431 0 : if (isset(self::$content_class_cache[$source_key]['compiled'][$compiled_key])) {
2432 0 : return self::$content_class_cache[$source_key]['compiled'][$compiled_key];
2433 : }
2434 0 : }
2435 : // load Compiled resource handler
2436 0 : $compiled_obj = $this->_loadHandler(self::COMPILED);
2437 0 : $compiled_obj->compile_id = $compile_id;
2438 0 : $compiled_obj->caching = $caching;
2439 0 : $compiled_obj->source = $source;
2440 0 : $compiled_obj->populate($this);
2441 0 : $compiled_obj->loadContent($this);
2442 0 : $content_obj = $compiled_obj->smarty_content;
2443 :
2444 : // save in cache?
2445 0 : if ($this->cache_objs) {
2446 0 : self::$content_class_cache[$source_key]['compiled'][$compiled_key] = $content_obj;
2447 0 : }
2448 :
2449 0 : return $content_obj;
2450 : }
2451 :
2452 : /**
2453 : *
2454 : * @params Smarty_Resource $source source resource
2455 : * @params mixed $compile_id compile id
2456 : * @params boolean $caching caching enabled ?
2457 : * @return Smarty_ResourceCompiled
2458 : */
2459 : public function _loadCompiled(Smarty_Resource $source, $compile_id, $caching = false)
2460 : {
2461 : // check runtime cache
2462 971 : $source_key = $source->uid;
2463 971 : $compiled_key = $compile_id ? $compile_id : '#null#';
2464 971 : if ($caching) {
2465 95 : $compiled_key .= '#caching';
2466 95 : }
2467 971 : if ($this->cache_objs) {
2468 971 : if (isset(self::$resource_cache[$source_key]['compiled'][$compiled_key])) {
2469 75 : return self::$resource_cache[$source_key]['compiled'][$compiled_key];
2470 : }
2471 971 : }
2472 : // load Compiled resource handler
2473 971 : $compiled_obj = $this->_loadHandler(self::COMPILED);
2474 971 : $compiled_obj->compile_id = $compile_id;
2475 971 : $compiled_obj->caching = $caching;
2476 971 : $compiled_obj->source = $source;
2477 971 : $compiled_obj->populate($this);
2478 :
2479 : // save in cache?
2480 970 : if ($this->cache_objs) {
2481 970 : self::$resource_cache[$source_key]['compiled'][$compiled_key] = $compiled_obj;
2482 970 : }
2483 :
2484 970 : return $compiled_obj;
2485 : }
2486 :
2487 1 : public function _loadCached(Smarty_Resource $source, $compile_id, $cache_id, $caching)
2488 : {
2489 : // check runtime cache
2490 139 : $source_key = $source->uid;
2491 139 : $compiled_key = $compile_id ? $compile_id : '#null#';
2492 139 : $cache_key = $cache_id ? $cache_id : '#null#';
2493 139 : if ($this->cache_objs && isset(self::$resource_cache[$source_key]['cache'][$compiled_key][$cache_key])) {
2494 34 : return self::$resource_cache[$source_key]['cache'][$compiled_key][$cache_key];
2495 : } else {
2496 : // load Cache resource handler
2497 139 : $cached_obj = $this->_loadHandler(self::CACHE);
2498 135 : $cached_obj->compile_id = $compile_id;
2499 135 : $cached_obj->cache_id = $cache_id;
2500 135 : $cached_obj->caching = $caching;
2501 135 : $cached_obj->source = $source;
2502 135 : $cached_obj->populate($this);
2503 : // save in cache?
2504 135 : if ($this->cache_objs) {
2505 135 : self::$resource_cache[$source_key]['cache'][$compiled_key][$cache_key] = $cached_obj;
2506 135 : }
2507 :
2508 135 : return $cached_obj;
2509 : }
2510 : }
2511 :
2512 : /**
2513 : * Get handler and create resource object
2514 : *
2515 : * @param int $res_type SOURCE|COMPILED|CACHE
2516 : * @param string $resource name of template_resource or the resource handler
2517 : * @throws Smarty_Exception
2518 : * @return Smarty_Resource Resource Handler
2519 : */
2520 : public function _loadHandler($res_type, $resource = null)
2521 : {
2522 : static $res_params = array(
2523 : self::SOURCE => array('Smarty_Resource', 'Smarty_Resource_'),
2524 : self::COMPILED => array('Smarty_Compiled_Resource', 'Smarty_Compiled_Resource_'),
2525 : self::CACHE => array('Smarty_Cache_Resource', 'Smarty_Cache_Resource_'),
2526 1127 : );
2527 :
2528 : switch ($res_type) {
2529 1127 : case self::SOURCE:
2530 1101 : if ($resource == null) {
2531 0 : $resource = $this->template_resource;
2532 0 : }
2533 : // parse template_resource into name and type
2534 1101 : $parts = explode(':', $resource, 2);
2535 1101 : if (!isset($parts[1]) || !isset($parts[0][1])) {
2536 : // no resource given, use default
2537 : // or single character before the colon is not a resource type, but part of the filepath
2538 291 : $type = $this->default_resource_type;
2539 291 : $name = $resource;
2540 291 : } else {
2541 850 : $type = $parts[0];
2542 850 : $name = $parts[1];
2543 : }
2544 1101 : break;
2545 1050 : case self::COMPILED:
2546 990 : $type = $resource ? $resource : $this->compiled_type;
2547 990 : break;
2548 255 : case self::CACHE:
2549 255 : $type = $resource ? $resource : $this->caching_type;
2550 255 : break;
2551 : }
2552 :
2553 1127 : $res_obj = null;
2554 : // try registered resource
2555 1127 : if (isset($this->registered_resources[$res_type][$type])) {
2556 22 : if ($this->registered_resources[$res_type][$type] instanceof $res_params[$res_type][0]) {
2557 22 : $res_obj = clone $this->registered_resources[$res_type][$type];
2558 22 : } else {
2559 0 : return new Smarty_Resource_Registered();
2560 : }
2561 1127 : } elseif (isset(self::$system_resources[$res_type][$type])) {
2562 : // try Smartys core Rescource
2563 1084 : $_resource_class = $res_params[$res_type][1] . ucfirst($type);
2564 1084 : $res_obj = new $_resource_class($this);
2565 1123 : } elseif ($this->_loadPlugin($_resource_class = $res_params[$res_type][2] . ucfirst($type))) {
2566 0 : if (class_exists($_resource_class, false)) {
2567 0 : $res_obj = new $_resource_class();
2568 0 : } else {
2569 : /**
2570 : * @TODO This must be rewritten
2571 : *
2572 : */
2573 0 : $this->registerResource($type, array(
2574 0 : "smarty_resource_{$type}_source",
2575 0 : "smarty_resource_{$type}_timestamp",
2576 0 : "smarty_resource_{$type}_secure",
2577 0 : "smarty_resource_{$type}_trusted"
2578 0 : ));
2579 :
2580 : // give it another try, now that the resource is registered properly
2581 0 : return $this->_loadHandler($res_type);
2582 : }
2583 0 : } else {
2584 :
2585 : // try streams
2586 0 : $_known_stream = stream_get_wrappers();
2587 0 : if (in_array($type, $_known_stream)) {
2588 : // is known stream
2589 0 : if (is_object($this->security_policy)) {
2590 0 : $this->security_policy->isTrustedStream($type);
2591 0 : }
2592 0 : $res_obj = new Smarty_Resource_Stream();
2593 0 : }
2594 : }
2595 :
2596 1088 : if ($res_obj) {
2597 1088 : if ($res_type == self::SOURCE) {
2598 1073 : $res_obj->name = $name;
2599 1073 : $res_obj->type = $type;
2600 1073 : if ($res_obj instanceof Smarty_Resource_Uncompiled) {
2601 0 : $res_obj->uncompiled = true;
2602 0 : }
2603 1073 : if ($res_obj instanceof Smarty_Resource_Recompiled) {
2604 1 : $res_obj->recompiled = true;
2605 1 : }
2606 1073 : }
2607 : // return create resource object
2608 1088 : return $res_obj;
2609 : }
2610 :
2611 : // TODO: try default_(template|config)_handler
2612 : // give up
2613 0 : throw new Smarty_Exception("Unknown resource type '{$type}'");
2614 : }
2615 :
2616 : /**
2617 : * runtime error for not matching capture tags
2618 : *
2619 : */
2620 : public function _capture_error()
2621 : {
2622 0 : throw new Smarty_Exception_Runtime("Not matching {capture} open/close", $this);
2623 : }
2624 :
2625 : /**
2626 : * Get parent or root of template parent chain
2627 : *
2628 : * @param int $scope_type parent or root scope
2629 : * @return mixed object
2630 : */
2631 : public function _getScopePointer($scope_type)
2632 : {
2633 0 : if ($scope_type == self::SCOPE_PARENT && !empty($this->parent)) {
2634 0 : return $this->parent;
2635 0 : } elseif ($scope_type == self::SCOPE_ROOT && !empty($this->parent)) {
2636 0 : $ptr = $this->parent;
2637 0 : while (!empty($ptr->parent)) {
2638 0 : $ptr = $ptr->parent;
2639 0 : }
2640 :
2641 0 : return $ptr;
2642 : }
2643 :
2644 0 : return null;
2645 : }
2646 :
2647 : /**
2648 : * Get Template Configuration Information
2649 : *
2650 : * @param boolean $html return formatted HTML, array else
2651 : * @param integer $flags see Smarty_Internal_Info constants
2652 : * @return string|array configuration information
2653 : */
2654 : public function infotpl_obj($html = true, $flags = 0)
2655 : {
2656 0 : $info = new Smarty_Internal_Info($this->smarty, $this);
2657 :
2658 0 : return $html ? $info->getHtml($flags) : $info->getArray($flags);
2659 : }
2660 :
2661 : /**
2662 : * Handle unknown class methods
2663 : *
2664 : * @param string $name unknown method-name
2665 : * @param array $args argument array
2666 : * @throws Smarty_Exception
2667 : * @return $this|bool|\Smarty_Compiled|\Smarty_template_Cached|\Smarty_Template_Source
2668 : */
2669 : public function __call($name, $args)
2670 : {
2671 4 : static $_prefixes = array('set' => true, 'get' => true);
2672 4 : static $_resolved_property_name = array();
2673 :
2674 : // see if this is a set/get for a property
2675 4 : $first3 = strtolower(substr($name, 0, 3));
2676 4 : if (isset($_prefixes[$first3]) && isset($name[3]) && $name[3] !== '_') {
2677 4 : if (isset($_resolved_property_name[$name])) {
2678 3 : $property_name = $_resolved_property_name[$name];
2679 3 : } else {
2680 : // try to keep case correct for future PHP 6.0 case-sensitive class methods
2681 : // lcfirst() not available < PHP 5.3.0, so improvise
2682 2 : $property_name = strtolower(substr($name, 3, 1)) . substr($name, 4);
2683 : // convert camel case to underscored name
2684 2 : $property_name = preg_replace_callback('/([A-Z])/', array($this, 'replaceCamelcase'), $property_name);
2685 2 : $_resolved_property_name[$name] = $property_name;
2686 : }
2687 4 : if ($first3 == 'get') {
2688 2 : return $this->$property_name;
2689 : } else {
2690 4 : return $this->$property_name = $args[0];
2691 : }
2692 : }
2693 0 : if ($name == 'Smarty') {
2694 0 : throw new Smarty_Exception("PHP5 requires you to call __construct() instead of Smarty()");
2695 : }
2696 : // throw error through parent
2697 0 : parent::__call($name, $args);
2698 0 : }
2699 :
2700 : /**
2701 : * preg_replace callback to convert camelcase getter/setter to underscore property names
2702 : *
2703 : * @param string $match match string
2704 : * @return string replacemant
2705 : */
2706 : private function replaceCamelcase($match)
2707 : {
2708 2 : return "_" . strtolower($match[1]);
2709 : }
2710 :
2711 : /*
2712 : EVENTS:
2713 : filesystem:write
2714 : filesystem:delete
2715 : */
2716 :
2717 : // TODO: document registerCallback()
2718 : public static function registerCallback($event, $callback = null)
2719 : {
2720 1 : if (is_array($event)) {
2721 0 : foreach ($event as $_event => $_callback) {
2722 0 : if (!is_callable($_callback)) {
2723 0 : throw new Smarty_Exception("registerCallback(): \"{$_event}\" not callable");
2724 : }
2725 0 : self::$_callbacks[$_event][] = $_callback;
2726 0 : }
2727 0 : } else {
2728 1 : if (!is_callable($callback)) {
2729 0 : throw new Smarty_Exception("registerCallback(): \"{$event}\" not callable");
2730 : }
2731 1 : self::$_callbacks[$event][] = $callback;
2732 : }
2733 1 : }
2734 :
2735 : // TODO: document triggerCallback()
2736 : public static function triggerCallback($event, $data)
2737 : {
2738 208 : if (isset(self::$_callbacks[$event])) {
2739 134 : foreach (self::$_callbacks[$event] as $callback) {
2740 134 : call_user_func_array($callback, (array) $data);
2741 134 : }
2742 134 : }
2743 208 : }
2744 :
2745 : /**
2746 : * Class destructor
2747 : */
2748 : public function __destruct()
2749 : {
2750 39 : if ($this->usage == self::IS_TEMPLATE && $this->cache_locking && isset($this->cached) && $this->cached->is_locked) {
2751 0 : $this->cached->releaseLock($this, $this->cached);
2752 0 : }
2753 39 : parent::__destruct();
2754 39 : }
2755 :
2756 : /**
2757 : * <<magic>> method
2758 : * remove resource objs
2759 : */
2760 : public function __clone()
2761 : {
2762 853 : $this->source = null;
2763 853 : }
2764 :
2765 : /**
2766 : * <<magic>> Generic getter.
2767 : * Get Smarty or Template property
2768 : *
2769 : * @param string $property_name property name
2770 : * @throws Smarty_Exception
2771 : * @return $this|bool|\Smarty_Compiled|\Smarty_template_Cached|\Smarty_Template_Source
2772 : */
2773 : public function __get($property_name)
2774 : {
2775 : static $getter = array(
2776 : 'template_dir' => 'getTemplateDir',
2777 : 'config_dir' => 'getConfigDir',
2778 : 'plugins_dir' => 'getPluginsDir',
2779 : 'compile_dir' => 'getCompileDir',
2780 : 'cache_dir' => 'getCacheDir',
2781 119 : );
2782 : switch ($property_name) {
2783 119 : case 'compiled':
2784 75 : return $this->_loadCompiled($this->source, $this->compile_id, $this->caching);
2785 50 : case 'cached':
2786 39 : return $this->_loadCached($this->source, $this->compile_id, $this->cache_id, $this->caching);
2787 11 : case 'mustCompile':
2788 5 : return !$this->compiled->isValid;
2789 :
2790 : }
2791 : switch ($property_name) {
2792 6 : case 'template_dir':
2793 6 : case 'config_dir':
2794 6 : case 'plugins_dir':
2795 6 : case 'compile_dir':
2796 6 : case 'cache_dir':
2797 0 : return $this->{$getter[$property_name]}();
2798 : }
2799 : // throw error through parent
2800 6 : parent::__get($property_name);
2801 0 : }
2802 :
2803 : /**
2804 : * <<magic>> Generic setter.
2805 : * Set Smarty or Template property
2806 : *
2807 : * @param string $property_name property name
2808 : * @param mixed $value value
2809 : * @throws Smarty_Exception
2810 : */
2811 : public function __set($property_name, $value)
2812 : {
2813 : static $setter = array(
2814 : 'template_dir' => 'setTemplateDir',
2815 : 'config_dir' => 'setConfigDir',
2816 : 'plugins_dir' => 'setPluginsDir',
2817 : 'compile_dir' => 'setCompileDir',
2818 : 'cache_dir' => 'setCacheDir',
2819 0 : );
2820 : switch ($property_name) {
2821 0 : case 'template_dir':
2822 0 : case 'config_dir':
2823 0 : case 'plugins_dir':
2824 0 : case 'compile_dir':
2825 0 : case 'cache_dir':
2826 0 : $this->{$setter[$property_name]}($value);
2827 :
2828 0 : return;
2829 : }
2830 :
2831 : // throw error through parent
2832 0 : parent::__set($property_name, $value);
2833 0 : }
2834 :
2835 : }
2836 :
2837 : // Check if we're running on windows
2838 : Smarty::$_IS_WINDOWS = strtoupper(substr(PHP_OS, 0, 3)) === 'WIN';
2839 :
2840 : // let PCRE (preg_*) treat strings as ISO-8859-1 if we're not dealing with UTF-8
2841 : if (Smarty::$_CHARSET !== 'UTF-8') {
2842 : Smarty::$_UTF8_MODIFIER = '';
2843 : }
|